* xdisp.c (display_text_line): Apply faces to characters
authorJim Blandy <jimb@redhat.com>
Mon, 10 May 1993 00:26:32 +0000 (00:26 +0000)
committerJim Blandy <jimb@redhat.com>
Mon, 10 May 1993 00:26:32 +0000 (00:26 +0000)
according to overlays and text properties; use
compute_char_face and compute_glyph_face to figure out what
face to use, and where a new face starts.
* xterm.c (dumpglyphs): Use the upper bits of the glyphs to decide
which frame face to use.  Call GLYPH_FOLLOW_ALIASES to make sure
we're implementing the glyph table properly.  If we're not using
the default or mode line face, call intern_face to find a display
face for the frame face selected by the glyph code.  Implement
underlining.  Remove the `font' argument; we have to derive this
from the frame and face anyway.  Change all callers.
* disptab.h (GLYPH_FOLLOW_ALIASES): New macro.

* xterm.c (x_destroy_window): Call free_frame_faces.

src/xterm.c

index d5ed6dfe19a0366345c6a4b0fefbe64b39fd9836..97ebb079acfc77b367b914d04e02deb679832ed3 100644 (file)
@@ -395,65 +395,42 @@ XTcursor_to (row, col)
    WINDOW is the x-window to output to.  LEFT and TOP are starting coords.
    HL is 1 if this text is highlighted, 2 if the cursor is on it.
 
-   FONT is the default font to use (for glyphs whose font-code is 0).  */
+   FONT is the default font to use (for glyphs whose font-code is 0).
 
-static void
-dumpglyphs (f, left, top, gp, n, hl, font)
-     struct frame *f;
-     int left, top;
-     register GLYPH *gp; /* Points to first GLYPH. */
-     register int n;  /* Number of glyphs to display. */
-     int hl;
-     FONT_TYPE *font;
-{
-  register int len;
-  Window window = FRAME_X_WINDOW (f);
-  GC drawing_gc =   (hl == 2 ? f->display.x->cursor_gc
-                            : (hl ? f->display.x->reverse_gc
-                                  : f->display.x->normal_gc));
+   Since the display generation code is responsible for calling
+   compute_char_face and compute_glyph_face on everything it puts in
+   the display structure, we can assume that the face code on each
+   glyph is a valid index into FRAME_FACES (f), and the one to which
+   we can actually apply intern_face.  */
 
-  if (sizeof (GLYPH) == sizeof (XChar2b))
-    XDrawImageString16 (x_current_display, window, drawing_gc,
-                       left, top + FONT_BASE (font), (XChar2b *) gp, n);
-  else if (sizeof (GLYPH) == sizeof (unsigned char))
-    XDrawImageString (x_current_display, window, drawing_gc,
-                     left, top + FONT_BASE (font), (char *) gp, n);
-  else
-    /* What size of glyph ARE you using?  And does X have a function to
-       draw them?  */
-    abort ();
-}
+#if 1
+/* This is the multi-face code.  */
 
-#if 0
 static void
-dumpglyphs (f, left, top, gp, n, hl, font)
+dumpglyphs (f, left, top, gp, n, hl)
      struct frame *f;
      int left, top;
      register GLYPH *gp; /* Points to first GLYPH. */
      register int n;  /* Number of glyphs to display. */
      int hl;
-     FONT_TYPE *font;
 {
-  char buf[f->width]; /* Holds characters to be displayed. */
+  /* Holds characters to be displayed. */
+  char *buf = (char *) alloca (f->width * sizeof (*buf));
   register char *cp;           /* Steps through buf[]. */
   register int tlen = GLYPH_TABLE_LENGTH;
   register Lisp_Object *tbase = GLYPH_TABLE_BASE;
   Window window = FRAME_X_WINDOW (f);
-  int cursor_pixel = f->display.x->cursor_pixel;
-  int fg_pixel = f->display.x->foreground_pixel;
-  int bg_pixel = f->display.x->background_pixel;
-  int intborder = f->display.x->internal_border_width;
 
-  while (n)
+  extern struct face *intern_face (/* FRAME_PTR, struct face * */);
+
+  while (n > 0)
     {
       /* Get the face-code of the next GLYPH.  */
       int cf, len;
       int g = *gp;
 
-      while (GLYPH_ALIAS_P (tbase, tlen, g))
-       g = GLYPH_ALIAS (tbase, g);
-       
-      cf = g >> 8;
+      GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
+      cf = GLYPH_FACE (g);
 
       /* Find the run of consecutive glyphs with the same face-code.
         Extract their character codes into BUF.  */
@@ -461,12 +438,11 @@ dumpglyphs (f, left, top, gp, n, hl, font)
       while (n > 0)
        {
          g = *gp;
-         while (GLYPH_ALIAS_P (tbase, tlen, g))
-           g = GLYPH_ALIAS (tbase, g);
-         if ((g >> 8) != cf)
+         GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
+         if (GLYPH_FACE (g) != cf)
            break;
 
-         *cp++ = 0377 & g;
+         *cp++ = GLYPH_CHAR (g);
          --n;
          ++gp;
        }
@@ -476,65 +452,96 @@ dumpglyphs (f, left, top, gp, n, hl, font)
 
       /* Now output this run of chars, with the font and pixel values
         determined by the face code CF.  */
-      if (cf == 0)
-       {
-#ifdef HAVE_X11
-         GC GC_cursor = f->display.x->cursor_gc;
-         GC GC_reverse = f->display.x->reverse_gc;
-         GC GC_normal = f->display.x->normal_gc;
-
-         XDrawImageString (x_current_display, window,
-                           (hl == 2
-                            ? GC_cursor
-                            : (hl ? GC_reverse : GC_normal)),
-                           left, top + FONT_BASE (font), buf, len);
-#else /* ! defined (HAVE_X11) */
-         XText (window, left, top,
-                buf,
-                len,
-                font->id,
-                (hl == 2
-                 ? (cursor_pixel == fg_pixel ? bg_pixel : fg_pixel)
-                 : hl ? bg_pixel : fg_pixel),
-                (hl == 2 ? cursor_pixel
-                 : hl ? fg_pixel : bg_pixel));
-#endif /* ! defined (HAVE_X11) */
-       }
-      else
+      {
+       struct face *face = FRAME_DEFAULT_FACE (f);
+       FONT_TYPE *font = FACE_FONT (face);
+       GC gc = FACE_GC (face);
+
+       if (cf != 0)
+         {
+           /* The face codes on the glyphs must be valid indices into the
+              frame's face table.  */
+           if (cf < 0 || cf >= FRAME_N_FACES (f))
+             abort ();
+
+           if (cf == 1)
+             face = FRAME_MODE_LINE_FACE (f);
+           else
+             face = intern_face (FRAME_FACES (f) [cf]);
+           font = FACE_FONT (face);
+           gc = FACE_GC (face);
+         }
+       else if (hl == 0)
+         ;
+       else if (hl == 1)
+         {
+           face = FRAME_MODE_LINE_FACE (f);
+           font = FACE_FONT (face);
+           gc   = FACE_GC   (face);
+         }
+       else if (hl == 2)
+         {
+           gc   = (f->display.x->cursor_gc);
+         }
+
+       XDrawImageString (x_current_display, window, gc,
+                         left, top + FONT_BASE (font), buf, len);
+       left += len * FONT_WIDTH (font);
+
+       /* We should probably check for XA_UNDERLINE_POSITION and
+          XA_UNDERLINE_THICKNESS properties on the font, but let's
+          just get the thing working, and come back to that.  */
        {
-#ifdef HAVE_X11
-         if (FACE_IS_FONT (cf))
-           XDrawImageString (x_current_display, FRAME_X_WINDOW (f),
-                             FACE_GC (cf),
-                             left, top + FONT_BASE (FACE_FONT (cf)),
-                             buf, len);
-         else if (FACE_IS_IMAGE (cf))
-           XCopyPlane (x_current_display, FACE_IMAGE (cf),
-                       FRAME_X_WINDOW (f),
-                       f->display.x->normal_gc,
-                       0, 0,
-                       FACE_IMAGE_WIDTH (cf),
-                       FACE_IMAGE_HEIGHT (cf), left, top);
-         else
-           abort ();
-#else /* ! defined (HAVE_X11) */
-         register struct face *fp = x_face_table[cf];
-
-         XText (window, left, top,
-                buf,
-                len,
-                fp->font->id,
-                (hl == 2
-                 ? (cursor_pixel == fp->fg ? fp->bg : fp->fg)
-                 : hl ? fp->bg : fp->fg),
-                (hl == 2 ? cursor_pixel
-                 : hl ? fp->fg : fp->bg));
-#endif /* ! defined (HAVE_X11) */
+         int underline_position = 2;
+
+         if (font->descent < underline_position)
+           underline_position = font->descent;
+
+         if (face->underline)
+           XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
+                           FACE_GC (face),
+                           left, (top
+                                  + FONT_BASE (font)
+                                  + underline_position),
+                           len * FONT_WIDTH (font), 1);
        }
-      left += len * FONT_WIDTH (font);
+
+       left += len * FONT_WIDTH (font);
+      }
     }
 }
-#endif /* ! 0 */
+#endif /* 1 */
+
+#if 0
+/* This is the old single-face code.  */
+
+static void
+dumpglyphs (f, left, top, gp, n, hl, font)
+     struct frame *f;
+     int left, top;
+     register GLYPH *gp; /* Points to first GLYPH. */
+     register int n;  /* Number of glyphs to display. */
+     int hl;
+     FONT_TYPE *font;
+{
+  register int len;
+  Window window = FRAME_X_WINDOW (f);
+  GC drawing_gc =   (hl == 2 ? f->display.x->cursor_gc
+                            : (hl ? f->display.x->reverse_gc
+                                  : f->display.x->normal_gc));
+
+  if (sizeof (GLYPH) == sizeof (XChar2b))
+    XDrawImageString16 (x_current_display, window, drawing_gc,
+                       left, top + FONT_BASE (font), (XChar2b *) gp, n);
+  else if (sizeof (GLYPH) == sizeof (unsigned char))
+    XDrawImageString (x_current_display, window, drawing_gc,
+                     left, top + FONT_BASE (font), (char *) gp, n);
+  else
+    /* What size of glyph ARE you using?  And does X have a function to
+       draw them?  */
+    abort ();
+}
+#endif
 \f
 /* Output some text at the nominal frame cursor position.
    Advance the cursor over the text.
@@ -567,7 +574,7 @@ XTwrite_glyphs (start, len)
   dumpglyphs (f,
              CHAR_TO_PIXEL_COL (f, curs_x),
              CHAR_TO_PIXEL_ROW (f, curs_y),
-             start, len, highlight, f->display.x->font);
+             start, len, highlight);
 
   /* If we drew on top of the cursor, note that it is turned off.  */
   if (curs_y == f->phys_cursor_y
@@ -1081,7 +1088,7 @@ dumprectangle (f, left, top, cols, rows)
                  CHAR_TO_PIXEL_COL (f, left),
                  CHAR_TO_PIXEL_ROW (f, y),
                  line, min (cols, active_frame->used[y] - left),
-                 active_frame->highlight[y], f->display.x->font);
+                 active_frame->highlight[y]);
     }
 
   /* Turn the cursor on if we turned it off.  */
@@ -3312,7 +3319,7 @@ x_draw_single_glyph (f, row, column, glyph, highlight)
   dumpglyphs (f,
              CHAR_TO_PIXEL_COL (f, column),
              CHAR_TO_PIXEL_ROW (f, row),
-             &glyph, 1, highlight, f->display.x->font);
+             &glyph, 1, highlight);
 }
 
 static void
@@ -4278,6 +4285,7 @@ x_destroy_window (f)
   if (f->display.x->icon_desc != 0)
     XDestroyWindow (XDISPLAY f->display.x->icon_desc);
   XDestroyWindow (XDISPLAY f->display.x->window_desc);
+  free_frame_faces (f);
   XFlushQueue ();
 
   xfree (f->display.x);